home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / umich / utils / sharsrc.arc / shar.c < prev   
C/C++ Source or Header  |  1990-03-20  |  15KB  |  630 lines

  1. /*
  2.  *  Shar puts readable text files together in a package
  3.  *  from which they are easy to extract.
  4.  *
  5.  *    v 860716 M. Kersenbrock (tektronix!copper!michaelk) for Z80-CPM
  6.  *    - enhanced usage message
  7.  *
  8.  *    v 860712 D. Wecker for ULTRIX and the AMIGA
  9.  *    - stripped down.. does patterns but no directories
  10.  *    - added a -u (unshar) switch
  11.  *
  12.  *    v 870128 R. Royar for ST
  13.  *    - removed #ifdefs that left stray }s in file
  14.  *    - reformatted text for consistant style
  15.  *    - modified main to abort when no files are given
  16.  *    - fixed call to fputc in tell macro, which omitted the stream
  17.  *      causing address errors on the ST.
  18.  *    - fixed STUPID coding in getopt that tried to write to
  19.  *      address 0++.
  20.  *    - known bugs:
  21.  *        still no directory support.  Extracting
  22.  *        files with directory names will get
  23.  *        only the directory name on an open call.
  24.  *
  25.  *    v 880713 J. Altstadt for ST
  26.  *    - removed extraneous #ifdefs for all other systems
  27.  *    - reformatted text for consistant style
  28.  *    - changed lots of things for unsharing:
  29.  *      1. added directory handling
  30.  *      2. added code to handle weird shar sed formats better,
  31.  *         will add more things when i get files that i can't unshar,
  32.  *         eg. when i get one of those icky sharchives that has split files
  33.  *         but won't add in the ability to handle shars that use awk to
  34.  *         extract files (yes, windsrch uses awk, blech!!!)
  35.  *      3. added in file overwrite protection, i didn't need it, but it was
  36.  *         easy (and i know i will need it some day when i don't have a
  37.  *         backup)
  38.  *      4. skip whitespace at begining of lines intended for sh, so it will
  39.  *         do stuff embedded in "if test" structures
  40.  *
  41.  *    v 890124 J. Altstadt for ST
  42.  *    - unshar will handle files split across two (or more) sharchives
  43.  *    - fixed bug that would allow creation of directories (files) with
  44.  *      the same name as an existing file (directory)
  45.  */
  46.  
  47.  
  48. #include <stdio.h>
  49. #include <osbind.h>
  50. #include <ctype.h>
  51. #include <stat.h>
  52.  
  53. long _stksize = 16 * 1024;    /* for 10k stack */
  54. char *Defenv = "ENOENV";    /* if no cc.ini file */
  55. extern char *getenv(),*malloc(),*index();
  56. void shar();
  57.  
  58.  
  59. #define BADCH    ((int)'?')
  60. #define EMSG    ""
  61. #define tell(s) {fputs(*nargv,stderr);fputs((s),stderr);fputc('\n',stderr);}
  62. #define rescanopts()    (optind = 1)
  63.  
  64. int    optind = 1,    /* index into parent argv vector */
  65.     optopt;        /* character checked for validity */
  66. long    fsize;        /* length of file */
  67. char    *optarg;    /* argument associated with option */
  68. char    *sav[100];    /* saved file names */
  69. int    savind;        /* save index */
  70.  
  71. /* OPTIONS */
  72. int    Verbose = 0;        /* provide append/extract feedback */
  73. int    Basename = 0;        /* extract into basenames */
  74. int    Count = 0;        /* count characters to check transfer */
  75. char    *Delim = "SHAR_EOF";    /* put after each file */
  76. char    Filter[100] = "cat";    /* used to extract archived files */
  77. char    *Prefix = NULL;        /* line prefix to avoid funny chars */
  78. int    OverWrite = 0;        /* do we overwrite an output file? */
  79.  
  80. char Usage1[] =
  81. "\nSHAR: Create/extract file archive for extraction by /bin/sh (normally).\n\
  82. \n\
  83. usage: shar [[-uo] archive] [[-a] [-p prefix]\
  84.  [-d delim] [-bcv] files > archive]\n\
  85. \n\
  86.     where:    -a    all the options (v,c,b,-pXX)\n";
  87.  
  88. char Usage2[] =
  89. "        -b    extract absolute paths into current directory\n\
  90.         -c    check filesizes on extraction\n\
  91.         -d    use this EOF delimiter instead of SHAR_EOF\n";
  92.  
  93. char Usage3[] =
  94. "        -o    unshar <archive>, overwriting old files\n\
  95.         -p    use this as prefix to each line in archived files\n\
  96.         -u    unshar <archive>, not overwriting old files\n\
  97.         -v    verbose on extraction, incl. echoing filesizes\n";
  98.  
  99.  
  100. #define SED "sed 's/^%s//'"    /* used to remove prefix from lines */
  101. #define OPTSTRING "u:o:ap:d:bcv"
  102.  
  103.  
  104. void main(argc, argv)
  105. int argc;
  106. char **argv;
  107. {
  108.     char *ppchFiles[256];
  109.     register int    C;
  110.     char **ppchList = ppchFiles;
  111.     register int errflg;
  112.     errflg = 0;
  113.  
  114.     while(EOF != (C = getopt(argc, argv, OPTSTRING))) {
  115.         switch(C) {
  116.         case 'v':
  117.             Verbose++;
  118.             break;
  119.         case 'c':
  120.             Count++;
  121.             break;
  122.         case 'b':
  123.             Basename++;
  124.             break;
  125.         case 'd':
  126.             Delim = optarg;
  127.             break;
  128.         case 'a': /* all the options */
  129.             optarg = "X";
  130.             Verbose++;
  131.             Count++;
  132.             Basename++;
  133.             /* fall through to set prefix */
  134.         case 'p':
  135.             sprintf(Filter, SED, Prefix = optarg);
  136.             break;
  137.         case 'o':
  138.             OverWrite++;
  139.         case 'u':
  140.             dounshar(optarg);
  141.             exit(0);
  142.             break;
  143.         default:
  144.             errflg++;
  145.         }
  146.     }
  147.  
  148.     C = getarg(argc, argv);
  149.     if (errflg || EOF == C) {
  150.         if (EOF == C)
  151.             fprintf(stderr, "shar: No input files\n");
  152.         fprintf(stderr, "%s%s%s", Usage1, Usage2, Usage3);
  153.         exit(1);
  154.     }
  155.     savind = 0;
  156.  
  157.     do {
  158.         if (getpat(optarg)) exit(2);
  159.     } while (EOF != (C = getarg(argc, argv)));
  160.  
  161.     sav[savind] = 0;
  162.     header(sav);
  163.     for (ppchList = sav; *ppchList; ++ppchList)
  164.         shar(*ppchList);
  165.     puts("#\tEnd of shell archive");
  166.     puts("exit 0");
  167.     exit(0);
  168. }
  169.  
  170.  
  171. int header(ppchFiles)
  172. char *ppchFiles[];
  173. {
  174.     char clock[40];
  175.     register char **ppchList;
  176.     char *pchOrg;
  177.     char *pchName;
  178.     register int    problems;
  179.     problems = 0;
  180.     pchOrg = getenv("organization");
  181.     pchName = getenv("name");
  182.     puts("#\tThis is a shell archive.");
  183.     puts("#\tRemove everything above and including the cut line.");
  184.     puts("#\tThen run the rest of the file through sh.");
  185.     puts("#----cut here-----cut here-----cut here-----cut here----#");
  186.     puts("#!/bin/sh");
  187.     puts("# shar:    Shell Archiver");
  188.     puts("#\tRun the following text with /bin/sh to create:");
  189.     for (ppchList = ppchFiles; *ppchList; ++ppchList)
  190.         printf("#\t%s\n", *ppchList);
  191.     stime(clock);
  192.     printf("# This archive created: %s",clock);
  193.     if (pchName)
  194.         printf("# By:\t%s (%s)\n", pchName,pchOrg);
  195.     return(0);
  196. }
  197.  
  198.  
  199. /* create an ASCII time string and copy it into timeline.  Caller
  200.  * should make sure timeline has ~35 characters space.
  201.  */
  202. stime(timeline)
  203. char timeline[];
  204. {
  205.     register int mytime;
  206.     register int date;
  207.     register int hours, minutes, seconds;
  208.     int day, month, year;
  209.     static char *months[] = {"January","February","March","April",
  210.                 "May","June","July","August","September",
  211.                 "October","November","December"};
  212.     char *tzone;
  213.     tzone = getenv("timezone");
  214.     mytime    = Tgettime();
  215.     date = Tgetdate();
  216.     seconds = (mytime&31)*2;
  217.     minutes = (mytime>>5)&63;
  218.     hours    = (mytime>>11)&31;
  219.     day = (date&31);
  220.     month = ((date>>5)&15)-1;
  221.     year = ((date>>9)&31)+1980;
  222.     sprintf(timeline,"%02d-%s-%d %d:%02d:%02d %s\n",
  223.     day,months[month],year,hours,minutes,seconds,tzone);
  224.     return(1);
  225. }
  226.  
  227.  
  228. int
  229. archive(input, output)
  230. char *input, *output;
  231. {
  232.     char line[BUFSIZ];
  233.     register FILE *ioptr;
  234.  
  235.     if (ioptr = fopen(input, "r")) {
  236.         printf("%s << \\%s > %s\n", Filter, Delim, output);
  237.         while(fgets(line, BUFSIZ, ioptr)) {
  238.             if (Prefix)
  239.                 fputs(Prefix, stdout);
  240.             fputs(line, stdout);
  241.             if (Count)
  242.                 fsize += strlen(line);
  243.         }
  244.         puts(Delim);
  245.         fclose(ioptr);
  246.         return(0);
  247.     }
  248.     else {
  249.         fprintf(stderr, "shar: Can't open '%s'\n", input);
  250.         return(1);
  251.     }
  252. }
  253.  
  254.  
  255. void shar(file)
  256. char *file;
  257. {
  258.     register char *basefile;
  259.     basefile = file;
  260.     if (!strcmp(file, "."))
  261.         return;
  262.     fsize = 0;
  263.     if (Basename) {
  264.         while(*basefile)
  265.             basefile++;        /* go to end of name */
  266.         while(basefile > file && *(basefile-1) != '/')
  267.             basefile--;
  268.     }
  269.     if (Verbose)
  270.         printf("echo shar: extracting %s\n", basefile);
  271.     if (archive(file, basefile))
  272.         exit(66);
  273.     if (Count) {
  274.         printf("if test %ld -ne \"`wc -c %s`\"\n",fsize,basefile);
  275.         printf("then\necho shar: error transmitting %s ",basefile);
  276.         printf("'(should have been %ld characters)'\nfi\n",fsize);
  277.     }
  278. }
  279.  
  280.  
  281. getpat(pattern)
  282. char *pattern;
  283. {
  284.     register char *ptr;
  285.  
  286.     ptr = pattern;
  287.     sav[savind] = malloc(strlen(ptr)+1);
  288.     strcpy(sav[savind++],ptr);
  289.     if (access(ptr,4)) {
  290.         printf("No read access for file: %s\n",ptr);
  291.         return(-1);
  292.     }
  293.     return(0);
  294. }
  295.  
  296.  
  297. /*
  298.  * get option letter from argument vector
  299.  */
  300. int
  301. getopt(nargc, nargv, ostr)
  302. int nargc;
  303. char **nargv, *ostr;
  304. {
  305.     register char    *oli;        /* option letter list index */
  306.     static char    *place = EMSG;    /* option letter processing */
  307.  
  308.     if(!*place) {            /* update scanning pointer */
  309.         if(optind >= nargc || *(place = nargv[optind])
  310.                 != '-' || !*++place)
  311.             return(EOF);
  312.         if (*place == '-') {    /* found "--" */
  313.             ++optind;
  314.             return(EOF);
  315.         }
  316.     }    /* option letter okay? */
  317.     if ((optopt = (int)*place++) == (int)':'
  318.             || !(oli = index(ostr,optopt))) {
  319.         if(!*place)
  320.             ++optind;
  321.         tell(": illegal optio